#include "common.h"

int tcp_connect(host,port)
  char *host;
  int port;
  {
    struct hostent *hp;
    struct sockaddr_in addr;
    int sock;
    
    if(!(hp=gethostbyname(host)))
      berr_exit("Couldn't resolve host");
    memset(&addr,0,sizeof(addr));
    addr.sin_addr=*(struct in_addr*)
      hp->h_addr_list[0];
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);

    if((sock=socket(AF_INET,SOCK_STREAM,
      IPPROTO_TCP))<0)
      err_exit("Couldn't create socket");
    if(connect(sock,(struct sockaddr *)&addr,
      sizeof(addr))<0)
      err_exit("Couldn't connect socket");
    
    return sock;
  }

/* Check that the common name matches the
   host name*/
void check_cert(ssl,host)
  SSL *ssl;
  char *host;
  {
    X509 *peer;
    char peer_CN[256];
    
    if(SSL_get_verify_result(ssl)!=X509_V_OK)
      berr_exit("Certificate doesn't verify");

    /*Check the cert chain. The chain length
      is automatically checked by OpenSSL when
      we set the verify depth in the ctx */

    /*Check the common name*/
    peer=SSL_get_peer_certificate(ssl);
    X509_NAME_get_text_by_NID(X509_get_subject_name(peer),NID_commonName, peer_CN, 256);
    if(strcasecmp(peer_CN,host))
    	err_exit("Common name doesn't match host name");
  }

/* Print the server certificate */
int print_cert(SSL *ssl)
{
	X509 *x=NULL;
	X509_CINF *ci;
	ASN1_STRING *str=NULL;
	EVP_PKEY *pkey=NULL;
	int ret=0;
	char *m=NULL;
	long l;

	x = SSL_get_peer_certificate(ssl);
	ci=x->cert_info;

	// HEADER
	if (BIO_write(bio_err,"Certificate:\n",13) <= 0) goto err;

	// VERSION
	l=X509_get_version(x);
	if (BIO_printf(bio_err,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;

	// SIGNATURE ALGORITHM
	if (BIO_printf(bio_err,"%8sSignature Algorithm: ","") <= 0)
		goto err;
	if (i2a_ASN1_OBJECT(bio_err, ci->signature->algorithm) <= 0)
		goto err;
	if (BIO_puts(bio_err, "\n") <= 0)
		goto err;

	// ISSUER
	if (BIO_printf(bio_err,"        Issuer:\n") <= 0) goto err;
	if (X509_NAME_print_ex(bio_err,X509_get_issuer_name(x),16,XN_FLAG_SEP_MULTILINE) < 0) goto err;
	if (BIO_write(bio_err,"\n",1) <= 0) goto err;

	// PUBLIC KEY
	if (BIO_write(bio_err,"        Subject Public Key Info:\n",33) <= 0)
		goto err;
	if (BIO_printf(bio_err,"%12sPublic Key Algorithm: ","") <= 0)
		goto err;
	if (i2a_ASN1_OBJECT(bio_err, ci->key->algor->algorithm) <= 0)
		goto err;
	if (BIO_puts(bio_err, "\n") <= 0)
		goto err;

	pkey=X509_get_pubkey(x);
	if (pkey == NULL) {
		BIO_printf(bio_err,"%12sUnable to load Public Key\n","");
	} else if (pkey->type == EVP_PKEY_RSA) {
		BIO_printf(bio_err,"%12sRSA Public Key: (%d bit)\n","",
				BN_num_bits(pkey->pkey.rsa->n));
		//RSA_print(bio_err,pkey->pkey.rsa,16);
	} else
		BIO_printf(bio_err,"%12sUnknown Public Key:\n","");

	// SIGNATURE
	if (BIO_puts(bio_err,"    Signature Algorithm: ") <= 0) goto err;
	if (i2a_ASN1_OBJECT(bio_err, x->sig_alg->algorithm) <= 0) goto err;
	BIO_write(bio_err,"\n",1);

err:
	if (str != NULL) ASN1_STRING_free(str);
	if (m != NULL) OPENSSL_free(m);
	return(ret);
}
